package algo_annotations.data.contrainte_superposition;

import algo_annotations.params.Params_a;
import algo_annotations.params.objects.ContrainteGeomSegment;
import commons.data.EchelleGeneralization;
import commons.data.Attributes;
import commons.data.Model;
import commons.drawing.SegmentDrawable;
import commons.io.in.Segment_in;
import commons.data.Zones;
import commons.utils.primitive_geom.Point_d;
import java.awt.Color;

// Ces segments ont des coordonnées fixes durant tout le traitement
// Les segments peuvent avoir une dissymétrie : on va donc décaler leur coordonnées
//  pour les placer au centre d'un lpus gros segments dont l'épaisseur totale vaudra
//  épaisseur_normale + épaisseur_dissymétrie
// On ne fera ce décalage que sur les segment optimisé, car ce décalage risquerait
//  de rendre les segments non contigus, et l'optimisation douglasPeuker ne fonctionnerait plus
public class SegmentFixe extends SegmentDrawable {

	// ATTRIBUTS
	protected Attributes attributes;
	public void setAttributes(Attributes attributes) {this.attributes = attributes;}
	public Attributes getAttributes() {return attributes;}
	public Model getModel() {return attributes.getModel();}

	// ZONE
	protected Zones zones;
	public Zones getZones() {return zones;}
	public void setZones(Zones zones) {this.zones = zones;}

	// CONTRAINTES GEOMETRIQUE (=epaisseur du segment)
	public ContrainteGeomSegment contrainteGeom;
	protected void setContrainteGeom(ContrainteGeomSegment cgs) {this.contrainteGeom = cgs;}
	public ContrainteGeomSegment getContrainteGeom() {return contrainteGeom;}

	// ECHELLE DE GENERALISATION
	protected EchelleGeneralization eg;
	public EchelleGeneralization getEchelleGeneralization() {return eg;}
	protected void setEchelleGeneralization(EchelleGeneralization eg) {this.eg = eg; updateEchelle();}

	
	private float largeurSeg_reel_m;
	public float getLargeurSeg_reel_m() {return largeurSeg_reel_m;}
	public void setLargeurSeg_reel_m(double l) {
		largeurSeg_reel_m = (float)l;
		// données de super pour l'affichage
		super.width_reel_m = (float)l;
	}


	// Pour traitement d'optimisation DouglasPeukler
	public SegmentFixe segConnectedTo;
	public SegmentFixe segConnectedFrom;

	// sert pendant l'optimisation pour savoir ou on en est du traitement
	// et également après, pour différentier les segment du groupes des seg optimise des autres (ceux d'origine)
	//  cf. getColor()
	public boolean bIsOptimized;


	public SegmentFixe(Segment_in seg, Params_a params) {
		super(seg, Color.GRAY, -1 , -1); // on va mettre a jour les largeurs dans init();
		this.attributes = seg.getAttributes_in();
		this.zones = seg.zones;
		this.setContrainteGeom(seg.contrainteGeomSegment);
		this.setEchelleGeneralization(seg.echelleGeneralization);
		init();
	}
	public SegmentFixe(SegmentFixe seg, Params_a params) {
		super(seg, Color.GRAY, -1 , -1); // on va mettre a jour les largeurs dans init();
		this.attributes = seg.attributes;
		this.zones = seg.zones;
		this.setContrainteGeom(seg.contrainteGeom);
		this.setEchelleGeneralization(seg.eg);
		init();
	}
	public SegmentFixe(Point_d pt1, Point_d pt2, Params_a params) {
		super(pt1, pt2, Color.GRAY, -1 , -1); // on va mettre a jour les largeurs dans init();
		init();
	}

	public void init() {
		this.segConnectedTo = null;
		this.segConnectedFrom = null;
		this.bIsOptimized = false;

		//precalculs pour optimiser, du fait que le segment est fixe
		computeBoundaries_and_Const();
	}

	// Affichage différentié selon que c'set un segment optimise ou non
	@Override
	public Color getColor() {
		if (bIsOptimized)
			return Color.GRAY;
		else
			return Color.LIGHT_GRAY;
	}

	// appelé dès qu'on définit une échelle de généralisation
	private void updateEchelle() {
		
		// c'est une erreur bloquante, mais elle est traitée par la suite par PreTraitementInputData
		if (contrainteGeom==null) return;

		largeurSeg_reel_m = (float) (contrainteGeom.epaisseur_papier_mm * eg.echelle_inv / 1000.0);

		// données de super pour l'affichage
		super.width_reel_m = largeurSeg_reel_m;
		super.width_topo_px = 1;
	}

	//rectangle englobant du segment, precalculé, pour accelerer des traitements ulterieurs

	public boolean bVertical;
	public boolean bHorizontal;

	//A appeler des que les coordonnees du segment sont renseignees ou ont change !!
	private void computeBoundaries_and_Const() {
		updateBound();

		bVertical = (pt1.x == pt2.x);
		bHorizontal = (pt1.y == pt2.y);
	}

	public void invert() {
		Point_d pt = pt1;
		pt1 = pt2;
		pt2 = pt;
	}

}
